package com.han.fu.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期工具类
 *
 * @author: star
 * @date: 2021-07-31
 */
@Slf4j
public class DateUtil {

    private static final String YEAR_ZH_CN = "年";
    private static final String MONTH_ZH_CN = "月";
    private static final String DAY_ZH_CN = "日";
    private static final String HOUR_ZH_CN = "时";
    private static final String MINUTE_ZH_CN = "分";
    private static final String SECOND_ZH_CN = "秒";
    private static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    private static final String DATE_FORMAT_CH = "yyyy年MM月dd日";

    /**
     * 获取当前日期 yyyy-mm-dd
     *
     * @return String
     */
    public static String getStringDateNow() {
        return LocalDate.now().toString();
    }


    /**
     * 获取当前时间 yyyy-mm-dd
     *
     * @return String
     */
    public static String getStringTimeNow() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        return LocalDateTime.now().format(formatter);
    }

    /**
     * 获取当前日期下num个日
     *
     * @return String
     */
    public static String getStringDateNextDays(int num) {
        LocalDate localDate = LocalDate.now().plusDays(num);
        return localDate.toString();
    }

    /**
     * 获取当前日期下num个月
     *
     * @return String
     */
    public static String getStringDateNextMonths(int num) {
        LocalDate localDate = LocalDate.now().plusMonths(num);
        return localDate.toString();
    }

    /**
     * 获取当前时间下i个日
     *
     * @return String
     */
    public static String getStringTimeNextDays(int num) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        LocalDateTime localDate = LocalDateTime.now().plusDays(num);
        return localDate.format(formatter);
    }

    /**
     * 获取当前时间下num个月
     *
     * @return String
     */
    public static String getStringTimeNextMonths(int num) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        LocalDateTime localDate = LocalDateTime.now().plusMonths(num);
        return localDate.format(formatter);
    }

    /**
     * 获取当前日期上num个日
     *
     * @return String
     */
    public static String getStringDateLastDays(int num) {
        LocalDate localDate = LocalDate.now().minusDays(num);
        return localDate.toString();
    }

    /**
     * 获取当前日期上num个月
     *
     * @return String
     */
    public static String getStringDateLastMonths(int num) {
        LocalDate localDate = LocalDate.now().minusMonths(num);
        return localDate.toString();
    }

    /**
     * 获取当前时间上num个日
     *
     * @return String
     */
    public static String getStringTimeLastDays(int num) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        LocalDateTime localDate = LocalDateTime.now().minusDays(num);
        return localDate.format(formatter);
    }

    /**
     * 获取当前时间上num个月
     *
     * @return String
     */
    public static String getStringTimeLastMonths(int num) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT);
        LocalDateTime localDate = LocalDateTime.now().minusMonths(num);
        return localDate.format(formatter);
    }

    /**
     * 计算相差时间
     *
     * @param time
     * @return
     */
    public static String calculateTime(Date time) {
        if (null == time) {
            return null;
        }
        // 获取当前时间的毫秒数
        long nowTime = System.currentTimeMillis();
        // 获取指定时间的毫秒数
        long reset = time.getTime();
        long dateDiff = nowTime - reset;
        return calculateTime(dateDiff);
    }

    /**
     * 智能计算相差时间
     *
     * @param time
     * @return
     */
    public static String intelligenceCalculateTime(Date time) {
        return intelligenceCalculateTime(dateChangeLocalDateTime(time));
    }

    /**
     * 智能计算相差时间
     *
     * @param time
     * @return
     */
    public static String intelligenceCalculateTime(LocalDateTime time) {
        if (null == time) {
            return null;
        }
        // 获取当前时间的毫秒数
        long nowTime = System.currentTimeMillis();
        // 获取指定时间的毫秒数
        long reset = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Long dateDiff = nowTime - reset;
        return getIntelligenceCalculateTime(dateDiff);
    }

    /**
     * 智能计算相差时间
     *
     * @param dateDiff
     * @return
     */
    public static String getIntelligenceCalculateTime(Long dateDiff) {
        if (null == dateDiff) {
            return null;
        }
        StringBuilder msg = new StringBuilder();
        if (dateDiff <= 60000) {
            msg.append("1分钟");
        } else {
            long day = dateDiff / 86400000;
            long hoursTime = dateDiff - (day * 86400000);
            long hours = hoursTime / 3600000;
            long minuteTime = hoursTime - (hours * 3600000);
            long minute = minuteTime / 60000;
            long secondTime = minuteTime - (minute * 60000);
            if (30 < day) {
                msg.append("30天以上");
            } else {
                if (0 < day) {
                    msg.append(day);
                    msg.append("天");
                }
                if (0 < hours) {
                    msg.append(hours);
                    msg.append(HOUR_ZH_CN);
                }
                if (0 < minute) {
                    msg.append(minute);
                    msg.append(MINUTE_ZH_CN);
                }
            }
        }
        return msg.toString();
    }

    /**
     * 计算相差时间
     *
     * @param time
     * @return
     */
    public static String calculateTime(LocalDateTime time) {
        if (null == time) {
            return null;
        }
        // 获取当前时间的毫秒数
        long nowTime = System.currentTimeMillis();
        StringBuilder msg = new StringBuilder();
        // 获取指定时间的毫秒数
        long reset = time.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        long dateDiff = nowTime - reset;

        return calculateTime(dateDiff);
    }

    /**
     * 计算相差时间
     *
     * @param dateDiff
     * @return
     */
    public static String calculateTime(Long dateDiff) {
        if (null == dateDiff) {
            return null;
        }
        StringBuilder msg = new StringBuilder();
        if (dateDiff <= 60000) {
            msg.append("刚刚");
        } else {
            long day = dateDiff / 86400000;
            long hoursTime = dateDiff - (day * 86400000);
            long hours = hoursTime / 3600000;
            long minuteTime = hoursTime - (hours * 3600000);
            long minute = minuteTime / 60000;
            long secondTime = minuteTime - (minute * 60000);
            long second = secondTime / 1000;
            long year = day / 365;
            long month = (day - (year * 365)) / 30;
            day = day - (year * 365) - (month * 30);
            if (0 < year) {
                msg.append(year);
                msg.append(YEAR_ZH_CN);
            }
            if (0 < month) {
                msg.append(month);
                msg.append(MONTH_ZH_CN);
            }
            if (0 < day) {
                msg.append(day);
                msg.append(DAY_ZH_CN);
            }
            if (0 < hours) {
                msg.append(hours);
                msg.append(HOUR_ZH_CN);
            }
            if (0 < minute) {
                msg.append(minute);
                msg.append(MINUTE_ZH_CN);
            }
            if (0 < second) {
                msg.append(second);
                msg.append(SECOND_ZH_CN);
            }
        }
        return msg.toString();
    }

    /**
     * 获取当前时间上num个日
     *
     * @return Date
     */
    public static Date getDateTimeLastDays(int num) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDate = LocalDateTime.now().minusDays(num);
        ZonedDateTime zdt = localDate.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 获取当前时间上num个周
     *
     * @return Date
     */
    public static Date getDateTimeLastWeeks(int num) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDate = LocalDateTime.now().minusWeeks(num);
        ZonedDateTime zdt = localDate.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 获取当前时间上num个时
     *
     * @return Date
     */
    public static Date getDateTimeLastHours(int num) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDate = LocalDateTime.now().minusHours(num);
        ZonedDateTime zdt = localDate.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * Date转LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalDate();
    }

    /**
     * 判断当前日期是否在日期范围以内
     *
     * @param now       比较日期
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return
     */
    public static boolean judgeDesignatedTimeScope(LocalDate now, LocalDate startDate, LocalDate endDate) {
        boolean loo = true;
        try {
            if (null != startDate && null != endDate && null != now) {
                startDate = startDate.minusDays(1);
                endDate = endDate.plusDays(1);
                if (now.isBefore(endDate) && now.isAfter(startDate)) {
                    loo = false;
                }
            }
        } catch (Exception e) {
            log.error("judgeDesignatedTimeScope 判断是否在时间范围以内解析参数异常：", e);
        }
        return loo;
    }

    /**
     * Date
     *
     * @return
     */
    public static Date getDateNow() {
        return new Date();
    }

    /**
     * LocalDate转Date
     *
     * @param date
     * @return LocalDateTime
     */
    public static LocalDateTime dateChangeLocalDateTime(Date date) {
        if (null == date) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * 格式化日期
     *
     * @param date
     * @return
     */
    public static Date parseDate(String date) {
        if (null != date) {
            SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
            try {
                return format.parse(date);
            } catch (ParseException e) {
                log.error("extractedDate解析日期:{}异常：", date, e);
            }
        }
        return null;
    }

    /**
     * 格式化日期
     *
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        if (null == date) {
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
        return format.format(date);
    }

    /**
     * 格式化中文日期
     *
     * @param date
     * @return
     */
    public static String formatDateCh(Date date) {
        if (null == date) {
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT_CH);
        return format.format(date);
    }

    /**
     * 格式化中文日期
     *
     * @param date
     * @return
     */
    public static Integer diffDate(Date date) {
        if (null == date) {
            return null;
        }
        LocalDate nowDate = LocalDate.now();
        LocalDate endDate = dateToLocalDate(date);
        return Period.between(endDate, nowDate).getDays();
    }
}
